﻿using Artech.Common;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Artech.Core.Configuration
{
    public class ServiceLocationSettings : SerializableConfigurationSection, ITypeRegistrationsProvider
    {
        private const string PropertyName4ServiceLocators = "serviceLocators";
        private const string PropertyName4DefaultServiceLocator = "defaultServiceLocator";

        [ConfigurationProperty(PropertyName4DefaultServiceLocator, IsRequired = false, DefaultValue="")]
        public string DefaultServiceLocator
        {
            get { return base[PropertyName4DefaultServiceLocator] as string; }
            set { base[PropertyName4DefaultServiceLocator] = value; }
        }

        [ConfigurationProperty(PropertyName4ServiceLocators, IsRequired = true)]
        public NameTypeConfigurationElementCollection<ServiceLocatorDataBase, CustomServiceLocatorData> ServiceLocators
        {
            get
            {
                return (NameTypeConfigurationElementCollection<ServiceLocatorDataBase, CustomServiceLocatorData>)this[PropertyName4ServiceLocators];
            }
            set
            {
                this[PropertyName4ServiceLocators] = value;
            }
        }

        public IEnumerable<TypeRegistration> GetRegistrations(IConfigurationSource configurationSource)
        {
            IEnumerable<TypeRegistration> serviceLocatorTypeRegistrations = this.ServiceLocators.SelectMany(locator => locator.GetRegistrations(configurationSource));
            foreach (TypeRegistration registration in serviceLocatorTypeRegistrations)
            {
                if (registration.Name == this.DefaultServiceLocator)
                {
                    registration.IsDefault = true;
                    yield return registration;
                }
                else
                {
                    yield return registration;
                }
            }
        }

        public IEnumerable<TypeRegistration> GetUpdatedRegistrations(IConfigurationSource configurationSource)
        {
            return GetRegistrations(configurationSource);
        }

        public static ServiceLocationSettings GetSettings(IConfigurationSource configurationSource = null)
        {
            configurationSource = configurationSource ?? ConfigurationSourceFactory.Create();
            return configurationSource.GetSection(Constants.ConfigurationSections.ServiceLocation) as ServiceLocationSettings;
        }
    }
}